#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
void task0();//主线程进行的函数
void task1();//线程1进行的函数
void task2();//线程2进行的函数
int pipe0[2],pipe1[2],pipe2[2],pipe3[2];//四个无名管道
pthread_t thrd0,thrd1,thrd2;	//三个进程进行三种运算
int main()
{
	int ret;
	ret=pipe(pipe0);//向阶乘运算线程写数据   0 读 1 写 必须0读1写，返回来会报错
	ret=pipe(pipe1);//从阶乘运算线程读数据
	ret=pipe(pipe2);//向斐波那契运算线程写数据
	ret=pipe(pipe3);//从斐波那契运算线程读数据
	
	if(ret<0){	//如果创建发生错误
		perror("pipe not create");
		exit(EXIT_FAILURE);
	}
	//创建三个线程
	ret=pthread_create(&thrd0,NULL,(void *)task0,NULL);	
	ret=pthread_create(&thrd1,NULL,(void *)task1,NULL);
	ret=pthread_create(&thrd2,NULL,(void *)task2,NULL);
	if(ret){	//如果线程创建出错
		perror("ptrhead_create");
		exit(EXIT_FAILURE);
	}
	pthread_join(thrd2,NULL);//挂起当前线程切换到thrd2线程
	pthread_join(thrd1,NULL);//切换到thrd1线程
	pthread_join(thrd0,NULL);//切换到主线程
	exit(EXIT_SUCCESS);
}
//计算阶乘
int fx(int x)
{
	return x==1?1:fx(x-1)*x;
}
//计算斐波那契
int fy(int y)
{
	if(y==1||y==2)
		return 1;
	return fy(y-1)+fy(y-2);
}
//主线程
void task0()
{
	int x=5,y=7;
	//close(pipe0[0]);//此时关闭不需要的端口之后会报错，之后的线程也是如此
	//close(pipe2[0]);
	//close(pipe1[1]);
	//close(pipe3[1]);
	printf("write %d to thread 1\n",x);
	write(pipe0[1],&x,sizeof(int));	//向子进程1写入x让其进行运算
	printf("write %d to thread 2\n",y);
	write(pipe2[1],&y,sizeof(int));//向子进程2写入y让其进行运算
	read(pipe1[0],&x,sizeof(int));//从子进程1中读出计算结果
	read(pipe3[0],&y,sizeof(int));//从子进程2中读出计算结果
	printf("get answer from thread1 is %d,get answer from thread2 is %d\n",x,y);
	close(pipe0[1]);
	close(pipe2[1]);
	close(pipe1[0]);
	close(pipe3[0]);//关闭管道
	printf("f(x,y)=%d\n",x+y);	//打印运算结果
}
//计算阶乘的线程
void task1()
{
	int x;
	read(pipe0[0],&x,sizeof(int));//从管道中读出子进程将计算的值x
	//read(pipe0[1],&x,sizeof(int));//从管道中读出子进程将计算的值x 反回来会报错
	printf("thread 1 get data %d\n",x);
	x=fx(x);//计算阶乘值
	printf("thread 1 get answer %d\n",x);//计算出结果
	write(pipe1[1],&x,sizeof(int));//向管道中写入子进程的计算结果
	close(pipe0[0]);
	close(pipe1[1]);//关闭管道
}
//计算斐波那契数的线程
void task2()
{
	int y;
	read(pipe2[0],&y,sizeof(int));//从管道中读出子进程将计算的值y
	printf("thread2 get data %d\n",y);
	y=fy(y);	//计算斐波那契数
	printf("thread2 get answer %d\n",y);
	write(pipe3[1],&y,sizeof(int));//向管道中写入子进程的计算结果
	close(pipe2[0]);
	close(pipe3[1]);//关闭管道
}
